package service

import (
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	"go-file-perception-model/internal/config"
	"go-file-perception-model/internal/logger"
	"go-file-perception-model/internal/model"
	"go-file-perception-model/internal/repository"

	"go.uber.org/zap"
)

// DBDirectoryTreeService 基于数据库的目录树服务
type DBDirectoryTreeService struct {
	fileMonitorRepo repository.FileMonitorRepository
	config          *config.Config
}

// NewDBDirectoryTreeService 创建基于数据库的目录树服务实例
func NewDBDirectoryTreeService(fileMonitorRepo repository.FileMonitorRepository, cfg *config.Config) *DBDirectoryTreeService {
	return &DBDirectoryTreeService{
		fileMonitorRepo: fileMonitorRepo,
		config:          cfg,
	}
}

// SearchFilesInDatabase 在数据库中搜索文件
func (s *DBDirectoryTreeService) SearchFilesInDatabase(req model.DBDirectoryTreeSearchRequest) (*model.DirectoryTreeResponse, error) {
	startTime := time.Now()

	// 处理搜索路径
	searchPath := s.processSearchPath(req.SearchPath)

	// 编译正则表达式
	var regexPattern *regexp.Regexp
	var err error
	if req.Pattern != "" {
		regexPattern, err = regexp.Compile(req.Pattern)
		if err != nil {
			return nil, fmt.Errorf("invalid regex pattern: %w", err)
		}
	}

	// 从数据库获取所有已索引的文件
	files, err := s.fileMonitorRepo.GetAllIndexedFiles()
	if err != nil {
		return nil, fmt.Errorf("failed to get indexed files from database: %w", err)
	}

	logger.Info("Retrieved files from database",
		zap.Int("total_files", len(files)),
		zap.String("search_path", searchPath),
		zap.String("pattern", req.Pattern))

	// 过滤匹配的文件
	matchedFiles := s.filterMatchedFiles(files, regexPattern, searchPath)

	logger.Info("Filtered matched files", zap.Int("matched_files", len(matchedFiles)))

	// 构建目录树结构
	root := s.buildTreeFromMatchedFiles(matchedFiles)

	// 计算统计信息
	stats := s.calculateTreeStats(root)

	took := time.Since(startTime).Milliseconds()

	return &model.DirectoryTreeResponse{
		Root:          root,
		TotalFiles:    stats.FileNodes,
		TotalDirs:     stats.DirNodes,
		IndexedFiles:  len(matchedFiles),
		FilteredFiles: len(matchedFiles),
		Took:          took,
	}, nil
}

// processSearchPath 处理搜索路径
func (s *DBDirectoryTreeService) processSearchPath(searchPath string) string {
	if searchPath == "" {
		// 如果没有指定搜索路径，使用配置中的第一个索引目录
		if len(s.config.FileIndex.IndexDirectories) > 0 {
			return s.config.FileIndex.IndexDirectories[0]
		}
		return ""
	}

	// 判断是否为绝对路径
	if filepath.IsAbs(searchPath) {
		return searchPath
	}

	// 相对路径，使用配置的索引目录作为根路径
	if len(s.config.FileIndex.IndexDirectories) > 0 {
		return filepath.Join(s.config.FileIndex.IndexDirectories[0], searchPath)
	}

	return searchPath
}

// filterMatchedFiles 过滤匹配的文件
func (s *DBDirectoryTreeService) filterMatchedFiles(files []*model.FileMonitorRecord, regexPattern *regexp.Regexp, searchPath string) []*model.FileMonitorRecord {
	var matched []*model.FileMonitorRecord

	for _, file := range files {
		// 检查路径过滤
		if searchPath != "" && !strings.HasPrefix(file.FilePath, searchPath) {
			continue
		}

		// 检查正则表达式匹配
		if regexPattern != nil {
			// 匹配文件名或文件路径
			if regexPattern.MatchString(file.FileName) || regexPattern.MatchString(file.FilePath) {
				matched = append(matched, file)
			}
		} else {
			// 如果没有正则表达式，返回所有在搜索路径下的文件
			matched = append(matched, file)
		}
	}

	return matched
}

// buildTreeFromMatchedFiles 从匹配的文件构建目录树
func (s *DBDirectoryTreeService) buildTreeFromMatchedFiles(files []*model.FileMonitorRecord) *model.DirectoryTreeNode {
	if len(files) == 0 {
		return nil
	}

	// 创建路径到节点的映射
	pathToNode := make(map[string]*model.DirectoryTreeNode)

	// 找到公共根路径
	commonRoot := s.findCommonRootPath(files)

	// 获取配置的索引目录
	var indexDirectory string
	if len(s.config.FileIndex.IndexDirectories) > 0 {
		indexDirectory = s.config.FileIndex.IndexDirectories[0]
	}

	// 创建根节点
	root := &model.DirectoryTreeNode{
		Name:       filepath.Base(commonRoot),
		Path:       s.getRelativePath(commonRoot, indexDirectory),
		Type:       "directory",
		Size:       0,
		Extension:  "",
		ModTime:    time.Now(),
		IsIndexed:  true,
		Children:   make([]*model.DirectoryTreeNode, 0),
		Depth:      0,
		IsExpanded: true,
	}

	if commonRoot == "" {
		root.Name = "搜索结果"
		root.Path = "/"
	}

	pathToNode[commonRoot] = root

	// 为每个匹配的文件创建完整的路径结构
	for _, file := range files {
		s.ensurePathExists(file.FilePath, pathToNode, commonRoot, indexDirectory)

		// 创建文件节点
		fileNode := &model.DirectoryTreeNode{
			Name:       file.FileName,
			Path:       s.getRelativePath(file.FilePath, indexDirectory),
			Type:       "file",
			Size:       file.FileSize,
			Extension:  filepath.Ext(file.FileName),
			ModTime:    file.FileModTime,
			IsIndexed:  file.IsIndexed,
			Children:   nil,
			Depth:      s.calculateDepth(file.FilePath, commonRoot),
			IsExpanded: false,
		}

		// 将文件节点添加到其父目录
		parentDir := filepath.Dir(file.FilePath)
		if parentNode, exists := pathToNode[parentDir]; exists {
			parentNode.Children = append(parentNode.Children, fileNode)
		}
	}

	// 排序所有节点的子节点
	s.sortTreeNodes(root)

	return root
}

// findCommonRootPath 找到所有文件的公共根路径
func (s *DBDirectoryTreeService) findCommonRootPath(files []*model.FileMonitorRecord) string {
	if len(files) == 0 {
		return ""
	}

	if len(files) == 1 {
		return filepath.Dir(files[0].FilePath)
	}

	// 获取第一个文件的路径作为基准
	commonPath := filepath.Dir(files[0].FilePath)

	// 与其他文件的路径比较，找到公共前缀
	for _, file := range files[1:] {
		filePath := filepath.Dir(file.FilePath)
		commonPath = s.findCommonPrefix(commonPath, filePath)
		if commonPath == "" {
			break
		}
	}

	return commonPath
}

// findCommonPrefix 找到两个路径的公共前缀
func (s *DBDirectoryTreeService) findCommonPrefix(path1, path2 string) string {
	// 标准化路径分隔符
	path1 = filepath.Clean(path1)
	path2 = filepath.Clean(path2)

	parts1 := strings.Split(path1, string(filepath.Separator))
	parts2 := strings.Split(path2, string(filepath.Separator))

	var commonParts []string
	minLen := len(parts1)
	if len(parts2) < minLen {
		minLen = len(parts2)
	}

	for i := 0; i < minLen; i++ {
		if parts1[i] == parts2[i] {
			commonParts = append(commonParts, parts1[i])
		} else {
			break
		}
	}

	if len(commonParts) == 0 {
		return ""
	}

	return strings.Join(commonParts, string(filepath.Separator))
}

// ensurePathExists 确保路径中的所有目录节点都存在
func (s *DBDirectoryTreeService) ensurePathExists(filePath string, pathToNode map[string]*model.DirectoryTreeNode, rootPath string, indexDirectory string) {
	dir := filepath.Dir(filePath)

	// 如果目录节点已存在，直接返回
	if _, exists := pathToNode[dir]; exists {
		return
	}

	// 递归确保父目录存在
	parentDir := filepath.Dir(dir)
	if parentDir != dir && parentDir != rootPath {
		s.ensurePathExists(dir, pathToNode, rootPath, indexDirectory)
	}

	// 创建当前目录节点
	dirNode := &model.DirectoryTreeNode{
		Name:       filepath.Base(dir),
		Path:       s.getRelativePath(dir, indexDirectory),
		Type:       "directory",
		Size:       0,
		Extension:  "",
		ModTime:    time.Now(),
		IsIndexed:  true,
		Children:   make([]*model.DirectoryTreeNode, 0),
		Depth:      s.calculateDepth(dir, rootPath),
		IsExpanded: true,
	}

	pathToNode[dir] = dirNode

	// 将目录节点添加到其父目录
	if parentNode, exists := pathToNode[parentDir]; exists {
		parentNode.Children = append(parentNode.Children, dirNode)
	}
}

// getRelativePath 获取相对于索引目录的相对路径
func (s *DBDirectoryTreeService) getRelativePath(absolutePath, indexDirectory string) string {
	if indexDirectory == "" {
		return absolutePath
	}
	
	// 计算相对路径
	relativePath, err := filepath.Rel(indexDirectory, absolutePath)
	if err != nil {
		// 如果计算相对路径失败，返回原始路径
		logger.Warn("Failed to calculate relative path", 
			zap.String("absolute_path", absolutePath), 
			zap.String("index_directory", indexDirectory), 
			zap.Error(err))
		return absolutePath
	}
	
	// 如果相对路径以 ".." 开头，说明文件不在索引目录内，返回原始路径
	if strings.HasPrefix(relativePath, "..") {
		return absolutePath
	}
	
	return relativePath
}

// calculateDepth 计算节点深度
func (s *DBDirectoryTreeService) calculateDepth(path, rootPath string) int {
	if rootPath == "" || path == rootPath {
		return 0
	}

	relPath, err := filepath.Rel(rootPath, path)
	if err != nil {
		return 0
	}

	if relPath == "." {
		return 0
	}

	return len(strings.Split(relPath, string(filepath.Separator)))
}

// sortTreeNodes 递归排序树节点
func (s *DBDirectoryTreeService) sortTreeNodes(node *model.DirectoryTreeNode) {
	if node == nil || len(node.Children) == 0 {
		return
	}

	// 排序子节点：目录在前，文件在后，同类型按名称排序
	sort.Slice(node.Children, func(i, j int) bool {
		child1, child2 := node.Children[i], node.Children[j]

		// 目录优先
		if child1.Type != child2.Type {
			return child1.Type == "directory"
		}

		// 同类型按名称排序
		return child1.Name < child2.Name
	})

	// 递归排序子节点
	for _, child := range node.Children {
		s.sortTreeNodes(child)
	}
}

// calculateTreeStats 计算树统计信息
func (s *DBDirectoryTreeService) calculateTreeStats(root *model.DirectoryTreeNode) *model.DirectoryTreeStats {
	if root == nil {
		return &model.DirectoryTreeStats{}
	}

	stats := &model.DirectoryTreeStats{}
	s.countNodes(root, stats)

	return stats
}

// countNodes 递归计算节点数量
func (s *DBDirectoryTreeService) countNodes(node *model.DirectoryTreeNode, stats *model.DirectoryTreeStats) {
	if node == nil {
		return
	}

	stats.TotalNodes++

	if node.Type == "directory" {
		stats.DirNodes++
	} else {
		stats.FileNodes++
		if node.IsIndexed {
			stats.IndexedNodes++
		}
	}

	for _, child := range node.Children {
		s.countNodes(child, stats)
	}
}
